var fy;
(function (fy) {
    let EnumNativeMethodType;
    (function (EnumNativeMethodType) {
        EnumNativeMethodType["all"] = "all";
        EnumNativeMethodType["syn"] = "syn";
        EnumNativeMethodType["asyn"] = "asyn";
    })(EnumNativeMethodType = fy.EnumNativeMethodType || (fy.EnumNativeMethodType = {}));
    /**
     * JS与原生的桥接器
     */
    let JsBridge;
    (function (JsBridge) {
        /**
         * 同步无返回
         * @param method 模块名称
         * @param args 参数
         */
        function synNoReturn(method, args) {
            let json = { action: method, params: args };
            JsBridge.call("synNoReturn", JSON.stringify(json));
        }
        JsBridge.synNoReturn = synNoReturn;
        /**
         * 同步有返回
         * @param method 模块名称
         * @param args 参数
         */
        function synHasReturn(method, args) {
            let json = { action: method, params: args };
            return JsBridge.call("synHasReturn", JSON.stringify(json));
        }
        JsBridge.synHasReturn = synHasReturn;
        /**
         * 异步
         * @param method 模块名称
         * @param cb 回调
         * @param args 参数
         */
        function async(method, cb, args) {
            let json = { action: method, params: args };
            JsBridge.call("async", JSON.stringify(json), (value) => {
                cb && cb(value);
            });
        }
        JsBridge.async = async;
        /**
         * 呼叫Native中的方法
         * @param method Java API 名称，可以包含命名空间
         * @param args 参数
         * @param cb 回调
         */
        function call(method, args, cb = null) {
            let ret = '';
            if (typeof args == 'function') { //无参数有回调的情况
                cb = args;
                args = {};
            }
            let arg = null;
            arg = { data: args === undefined ? null : args };
            if (typeof cb == 'function') {
                let cbName = 'objCount' + window.objCount++; //将方法定义为一个全局变量，用于后面调用
                window[cbName] = cb;
                arg['_dscbstub'] = cbName; //将方法名保存到arg中，用于Native端调用
            }
            arg = JSON.stringify(arg);
            //if in webview that dsBridge provided, call!
            if (window._dsbridge) {
                ret = window._dsbridge.call(method, arg);
            }
            else if (window._dswk || navigator.userAgent.indexOf("_dsbridge") != -1) { //使用时Native会注册_dswk参数
                ret = prompt("_dsbridge=" + method, arg); //调起原生代码
            }
            return JSON.parse(ret || '{}').data;
        }
        JsBridge.call = call;
        /**
         * Native调用的方法使用此方法注册
         * @param name 注册方法名
         * @param fun
         * @param async 是否异步,默认同步
         */
        function register(name, fun, async = false) {
            //注册的方法会保存到_dsaf或_dsf中
            let data = async ? window._asyncFun : window._synFun;
            if (!window._dsInit) {
                window._dsInit = true;
                //notify native that js apis register successfully on next event loop
                setTimeout(() => {
                    JsBridge.call("_dsb.dsinit", null, null);
                }, 0);
            }
            //object类型保存到_obs下，方法直接保存到_dsf(_asyncFun)下
            if (typeof fun == "object") {
                data._objs[name] = fun;
            }
            else {
                data[name] = fun;
            }
        }
        JsBridge.register = register;
        /**
         * Native调用的方法使用此方法注册(异步)
         * @param name 注册方法名
         * @param fun
         */
        function registerAsyn(name, fun) {
            this.register(name, fun, true);
        }
        JsBridge.registerAsyn = registerAsyn;
        /**
         * 检测Java中是否存在名为handlerName的API, handlerName可以包含命名空间.
         * @param handlerName
         * @param type ["all"|"syn"|"asyn" ]
         */
        function hasNativeMethod(handlerName, type = EnumNativeMethodType.all) {
            return this.call("_dsb.hasNativeMethod", { name: handlerName, type });
        }
        JsBridge.hasNativeMethod = hasNativeMethod;
        /**
         * 禁止Javascript对话框阻塞
         * @param disable
         */
        function disableJavascriptDialogBlock(disable) {
            this.call("_dsb.disableJavascriptDialogBlock", {
                disable: disable !== false
            });
        }
        JsBridge.disableJavascriptDialogBlock = disableJavascriptDialogBlock;
        /**初始化 */
        function init() {
            //判断是否需要给window进行参数添加，如果没有添加会把ob内参数进行一次添加
            if (window._synFun)
                return;
            var _close = window.close;
            var ob = {
                //存储同步方法相关object 
                _synFun: {
                    _objs: {}
                },
                //存储异步方法相关object
                _asyncFun: {
                    _objs: {}
                },
                objCount: 0,
                dsBridge: JsBridge,
                close: function () {
                    if (JsBridge.hasNativeMethod('_dsb.closePage', null)) {
                        JsBridge.call("_dsb.closePage", null, null);
                    }
                    else {
                        _close.call(window);
                    }
                },
                //处理Native调用js方法
                _handleMessageFromNative: function (info) {
                    var arg = JSON.parse(info.data);
                    var ret = null;
                    ret = {
                        id: info.callbackId,
                        complete: true
                    };
                    var synFun = this._synFun[info.method];
                    var asynFun = this._asyncFun[info.method];
                    var callSyn = function (synFun, ob) {
                        ret.data = synFun.apply(ob, arg);
                        JsBridge.call("_dsb.returnValue", ret, null); //js方法处理完后回调原生方法，并返回处理后的结果
                    };
                    var callAsyn = function (synFun, ob) {
                        arg.push(function (data, complete) {
                            ret.data = data;
                            ret.complete = complete !== false;
                            JsBridge.call("_dsb.returnValue", ret, null);
                        });
                        synFun.apply(ob, arg);
                    };
                    if (synFun) {
                        callSyn(synFun, this._synFun);
                    }
                    else if (asynFun) {
                        callAsyn(asynFun, this._asyncFun);
                    }
                    else {
                        //with namespace
                        var name = info.method.split('.');
                        if (name.length < 2)
                            return;
                        var method = name.pop();
                        var namespace = name.join('.');
                        var obs = this._synFun._objs;
                        var ob = obs[namespace] || {};
                        var m = ob[method];
                        if (m && typeof m == "function") {
                            callSyn(m, ob);
                            return;
                        }
                        obs = this._asyncFun._objs;
                        ob = obs[namespace] || {};
                        m = ob[method];
                        if (m && typeof m == "function") {
                            callAsyn(m, ob);
                            return;
                        }
                    }
                }
            };
            //将ob所有参数赋值给window
            for (var attr in ob) {
                window[attr] = ob[attr];
            }
            JsBridge.register("_hasJavascriptMethod", function (method, tag) {
                var name = method.split('.');
                if (name.length < 2) {
                    return !!(this._synFun[name] || this._asyncFun[name]); //js用!!进行bool转换
                }
                else {
                    // with namespace
                    var method = name.pop();
                    var namespace = name.join('.');
                    var ob = this._synFun._objs[namespace] || this._asyncFun._objs[namespace];
                    return ob && !!ob[method];
                }
            });
        }
        JsBridge.init = init;
    })(JsBridge = fy.JsBridge || (fy.JsBridge = {}));
    JsBridge.init();
})(fy || (fy = {}));
window.fy=fy;